/***************************************************************************
 *   Copyright (C) 2005 by xihe   *
 *   xihels@163.com                                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <string>
using std::string;
#include "QQBuddy.h"
QQGroupName::QQGroupName(const uint8_t* buf) 
{
    readBufB(group, buf++);
    const char* str = reinterpret_cast<const char*>(buf);
    groupname.assign(str, str + strlen(str) + 1);// = reinterpret_cast<const char*>(buf);
}

int QQBuddy::getBody(const uint8_t* buf, int len) 
{
    const uint8_t* cur = buf;
    /**
     * 1. 好友QQ号，4字节
     * 3. 头像，2字节
     * 4. 年龄，1字节
     * 5. 性别，1字节
     * 6. 昵称长度，1字节
     * 7. 昵称，不定字节，由5指定
     * 8. 2字节, 未知
     * 9. 1字节扩展标志，bit1表示是否有QQ Show，其他未知
     * 10.1字节通用标志
     *     bit1 => 会员
     *     bit4 => TCP方式登陆
     *     bit5 => 移动QQ
     *     bit6 => 绑定到手机
     *     bit7 => 是否有摄像头
     */
    cur += readBufDw(uid, cur);
    cur += readBufW(face, cur);
    cur += readBufB(age, cur);
    cur += readBufB(sex, cur);

    int nicklen = *cur++;
    nickname.reserve(nicklen);
    nickname.assign(cur, cur + nicklen);
    cur += nicklen;

    cur += 2;

    cur += readBufB(*reinterpret_cast<uint8_t*>(&extend), cur);
    cur += readBufB(*reinterpret_cast<uint8_t*>(&common), cur);

    return cur - buf;
}


int QQBuddyStatus::getBody(const uint8_t* buf, int len)
{
    /**
     * 好友状态结构
     * 000-003: 好友QQ号
     * 004: 0x01，未知含义
     * 005-008: 好友IP
     * 009-010: 好友端口
     * 011: 0x01，未知含义
     * 012: 好友状态
     * 013-014: 未知含义
     * 015-030: key，未知含义

*/
    const uint8_t* cur = buf;

    cur += readBufDw(uid, cur);
    cur++;
    cur += readBufDw(ip, cur);
    cur += readBufW(port, cur);
    cur++;
    cur += readBufB(status, cur);
    cur += 2;
    cur += writeBufData(unknownKey, cur, QQ_KEY_LENGTH);

    return cur - buf;
}

QQBuddyLevel::QQBuddyLevel(const uint8_t* buf, uint32_t)
{
    const uint8_t* cur = buf;
    cur += readBufDw(uid, cur);
    cur += readBufDw(onlineTime, cur);
    cur += readBufW(level, cur);
    cur += readBufW(timeRemainder, cur);
}


/**
 * 一个用户的详细信息，全部都是字符串形式，
 * 一共37项
 * 分割符(char)30
 */

/**
 * 1. QQ号
 * 2. 昵称
 * 3. 国家
 * 4. 省
 * 5. 邮政编码
 * 6. 地址
 * 7. 电话
 * 8. 年龄
 * 9. 性别
 * 10. 姓名
 * 11. Email
 * 12. 寻呼机sn，（sn是什么玩意，我也不知道）
 * 13. 寻呼机号
 * 14. 寻呼机服务提供商
 * 15. 寻呼机base num（也不清楚这是什么）
 * 16. 寻呼机类型
 * 17. 职业
 * 18. 主页
 * 19. 认证类型（应该是被人加自己为好友的时候的认证类型把）
 * 20. unknown 1
 * 21. unknown 2
 * 22. 头像，头像是用一个数代表的，比如27, 因为QQ目录下的头像是从1开始编号的，
 *     但是这个头像的数字却是从0开始计数的。并且注意，QQ的目录下面每种头像都
 *     有3个bmp，所以按数字这么一排，27应该是10-1.bmp
 * 23. 手机号
 * 24. 手机类型 
 * 25. 介绍
 * 26. 城市
 * 27. unknown 3
 * 28. unknown 4
 * 29. unknown 5
 * 30. is_open_hp
 * 31. is_open_contact（通讯方式是否对其他人可见）
 * 32. 学校
 * 33. 星座
 * 34. 生肖
 * 35. 血型
 * 36. QQ秀
 * 37. unknown 6，总是0x2D
 */
QQContact::QQContact(const char* buf, int len)
{
    buflen = len + 1;
    infobuf = new char[buflen]; 
    memcpy(infobuf, buf, len);
    infobuf[len] = '\0';
    char* cur = infobuf;
    char* max = cur + len;
    for (int i = 0; i < QQ_CONTACT_FIELDS; i++) {
	infos[i] = cur;
	for (; (cur < max) && (30 != *cur); cur++)
	    NULL;
	if (cur < max) {
	    *cur = '\0';
	    cur ++;
	} else if (i < QQ_CONTACT_FIELDS - 1) {
	    delete[] infobuf;
	    infobuf = NULL;
	    throw runtime_error("QQContact Error, info fields < QQ_CONTACT_FIELDS");
	} 
    } 
}

QQContact::QQContact(const QQContact& rhs)
{
    buflen = rhs.buflen;
    infobuf = new char[buflen];
    memcpy(infobuf, rhs.infobuf, buflen);
    for (int i = 0; i < QQ_CONTACT_FIELDS; i++)
	infos[i] = infobuf + (rhs.infos[i] - rhs.infobuf);


}

QQContact& QQContact::operator = (const QQContact& rhs)
{
    buflen = rhs.buflen;
    char* tmp = new char[buflen];
    memcpy(tmp, rhs.infobuf, buflen);
    for (int i = 0; i < QQ_CONTACT_FIELDS; i++)
	infos[i] = tmp + (rhs.infos[i] - rhs.infobuf);
    delete[] infobuf;
    infobuf = tmp;
}

/* 在线用户信息(用于搜索用户返回列表中)
 *    以0x1F相隔的用户数据，其中，一个用户的数据分4个域，域之间用0x1E相隔，四个域为
 *    i.   用户QQ号的字符串形式
 *    ii.  用户昵称
 *    iii. 用户所在地区
 *    iv.  用户的头像号码
 */
int QQOnlineUserInfo::getBody(const char* buf, int len)
{
    const char* cur = buf;
    const char* pch = buf;
    const char* max = buf + len;
    
    for (; (pch < max) && (0x1e != *pch); pch++) NULL;
    string str(cur, pch);
    str.append(1, '\0');
    uid = atoi(str.c_str());

    pch++;
    cur = pch;
    for (; (pch < max) && (0x1e != *pch); pch++) NULL;
    nickname.assign(cur, pch);
    nickname.append(1, '\0');

    pch++;
    cur = pch;
    for (; (pch < max) && (0x1e != *pch); pch++) NULL;
    province.assign(cur, pch);
    province.append(1, '\0');

    pch++;
    cur = pch;
    for (; (pch < max) && (0x1f != *pch); pch++) NULL;
    str.assign(cur, pch);
    str.append(1, '\0');
    face = atoi(str.c_str());

    return pch - buf;
}
